//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <elapi.h>
#include <eladef.h>
#include <stdio.h>
#include <critsec.h>

_ELASTOS_NAMESPACE_USING

EXTERN_C _ELASTOS Boolean AttachElauraDll();
EXTERN_C void DetachElauraDll();

EXTERN_C _ELASTOS Boolean __stdcall DllMain(
    PVoid hDllHandle,
    UInt32 dwReason,
    PVoid preserved)
{
    _ELASTOS Boolean ret = TRUE;
    // TODO: PALDisableThreadLibraryCalls((HMODULE)hModule);
    switch (dwReason) {
        case DLL_PROCESS_ATTACH:
            ret = AttachElauraDll();

            break;

        case DLL_PROCESS_DETACH:
            DetachElauraDll();

            // Do something
            // TODO: here need recycle the memory used by ezCOM
            break;
    }

    return ret;
}

EXTERN_C ECode __stdcall CrtFindService(WString wszName, IInterface **ppObj)
{
    return _CSystem_FindRunningObject(wszName, ppObj);
}

EXTERN_C ECode /* IApplet* */ __stdcall CrtGetCurrentAppletDir(WStringBuf* pwsAppletDir)
{
    IApplet* pApplet = NULL;
    ECode ec = _CApplet_GetCurrent((PInterface*)&pApplet);
    if (FAILED(ec)) return ec;

    ec = pApplet->GetCurrentDirectory(pwsAppletDir);
    pApplet->Release();
    return ec;
}

EXTERN_C ECode CrtInitializeLock(PVoid* ppLock)
{
    CCriticalSection *pLock = new CCriticalSection();
    if (pLock == NULL) {
        return E_OUT_OF_MEMORY;
    }

    *ppLock = pLock;

    return pLock->Initialize();
}

EXTERN_C ECode CrtEnterLock(PVoid pLock)
{
    if (pLock == NULL)
        return E_INVALID_OPERATION;

    CCriticalSection *lock = (CCriticalSection*)pLock;
    lock->Enter();

    return NOERROR;
}

EXTERN_C ECode CrtLeaveLock(PVoid pLock)
{
    if (pLock == NULL)
        return E_INVALID_OPERATION;

    CCriticalSection *lock = (CCriticalSection*)pLock;
    lock->Leave();

    return NOERROR;
}

EXTERN_C ECode CrtDeleteLock(PVoid* ppLock)
{
    if (!ppLock || !*ppLock)
        return E_INVALID_OPERATION;

    CCriticalSection *pLock = (CCriticalSection*)(*ppLock);
    pLock->Terminate();
    delete pLock;
    *ppLock = NULL;

    return NOERROR;
}
